﻿/*
 * Environment
 * 
 * initial implementation : 28.5.2011
 *
 * Copyright (c) Adam Sida, asida@centrum.cz.
 * All rights reserved.
 * 
 * for license see Petra.Gis.License.txt
 */
using System;
using System.IO;
using System.Reflection;
using System.Collections.Generic;
//using System.Linq;
//using System.Text;
using System.Windows.Markup;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using Petra.Gis.DocumentServices;
using Petra.Gis.Support;

namespace Petra.Gis
{


  /// <summary>
  /// Topmost class in Petra.Gis object hierarchy.
  /// Handles all application persistence services like system settings load,
  /// project open and save, library mgm and various object pooling
  /// </summary>
  public static partial class Environment
  {

    private static EnvironmentPersistablesBase _EP;

    private static bool _settingsChanged;
    private static bool _componentsChanged;
    private static bool _librariesChanged;

    private static GisSettings _settings;
    private static CustomComponents _components;
    private static GisLibraries _libraries;



    static Environment()
    {
      //load fixed values first
      _EP = new FixedSystemEnvironmentPersistables();

      _settingsChanged = true;
      _componentsChanged = true;
      _librariesChanged = true;

      //try load all persistables from predefined values...
      _loadSystemPersistables();
      //string strVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();

      //todo:if project needs to be open....
    }






    public static GisSettings Settings
    {
      get
      {
        //if settings not changed, return cached version...
        if (!_settingsChanged)
          return _settings;

        //otherwise create new cached version 
        _settings = new GisSettings();
        EnvironmentPersistablesBase tmp = _EP;
        //while (tmp.GetType() != typeof(SystemEnvironmentPersistables))
        while(tmp != null)
        {
          foreach (KeyValuePair<string, string> kvp in tmp.Settings)
            if (!_settings.ContainsKey(kvp.Key))
              _settings.Add(kvp);

          tmp = tmp.ParentPersistable;
        }
        _settingsChanged = false;
        return _settings;
      }
    }





    //load as second
    public static CustomComponents Components
    {
      get
      {
        if (!_componentsChanged)
          return _components;

        //otherwise create new cached version 
        _components = new CustomComponents();
        EnvironmentPersistablesBase tmp = _EP;
        //while (tmp.GetType() != typeof(SystemEnvironmentPersistables))
        while (tmp != null)
        {
          foreach (KeyValuePair<string, CustomComponentSet> kvp in tmp.Components)
            if (!_components.ContainsKey(kvp.Key))
              _components.Add(kvp.Key, kvp.Value);
            else
              //component set exists, check all components...
              _components[kvp.Key].Add(kvp.Value);
              
          tmp = tmp.ParentPersistable;
        }
        _componentsChanged = false;
        return _components;

      }
    }





    //load third
    //private static Libraries _libraries;

    public static GisLibraries Libraries
    {
      get 
      {
        if (!_librariesChanged)
          return _libraries;

        //otherwise create new cached version 
        _libraries = new GisLibraries();
        EnvironmentPersistablesBase tmp = _EP;
        while (tmp != null)
        {

          //merge coordinate system libraries
          _libraries.SRSLibrary.Add(tmp.Libraries.SRSLibrary.CoordinateSystems);


          //todo:merge another libraries....

          tmp = tmp.ParentPersistable;
        }
        _librariesChanged = false;
        return _libraries;

      }
    }





    #region Project

    private static Project _project;

    public static Project ActiveProject
    {
      get { return _project; }
      //set { _xDoc = value; }
    }





    public static void CreateProject(string projectName)
    {
      _project = new Project();
      _project.Metadata.Name = projectName;
    }





    public static bool OpenProject(Stream docStr)
    {
      try
      {
        _project = (Project)XamlReader.Load(docStr);

        //resolve persistables...
        _project.ProjectPersistables.ParentPersistable = _EP;
        _EP = _project.ProjectPersistables;
        return true;
      }
      catch { return false; }
    }





    public static void SaveProject(Stream docStr)
    {
      //FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write);
      XamlWriter.Save(_project, docStr);
    }



    #endregion Project





    public static bool OpenLibrary(Stream docStr)
    {
      try
      {
        throw new NotImplementedException();
        return true;
      }
      catch { return false; }
    }





    private static void _loadSystemPersistables()
    {
      string pathJson = GetSystemPath();

      if (pathJson == null)
        return;

      FileStream fsj = new FileStream(pathJson, FileMode.Open, FileAccess.Read);
      DataContractJsonSerializer outp = new DataContractJsonSerializer(typeof(SystemEnvironmentPersistables));

      SystemEnvironmentPersistables tmp = (SystemEnvironmentPersistables)outp.ReadObject(fsj);
      
      tmp.ParentPersistable = _EP;
      _EP = tmp;

      _settingsChanged = true;
      _componentsChanged = true;
      _librariesChanged = true;

      //Environment.Configuration.Settings = tmp.Configuration.Settings;
      //Environment.Configuration.Components = tmp.Configuration.Components;
      //Environment.Settings = tmp.Settings;
      //Environment.Components = tmp.Components;
      //Environment.Libraries = tmp.Libraries;

      fsj.Close();
    }





    private static bool _saveSystemPersistables()
    {
      string pathJson = GetSystemPath();

      if (pathJson == null)
        return false;

      EnvironmentPersistablesBase tmp = _EP;

      //extract SystemEnvironmentPersistables if exists
      while (tmp != null)
      {
        if (tmp.GetType() == typeof(SystemEnvironmentPersistables))
          break;

        tmp = tmp.ParentPersistable;
      }

      //nothing to save
      if (tmp == null)
        return false;

      //SystemEnvironmentPersistables tmp = (SystemEnvironmentPersistables)_EP;

      //tmp.Configuration.Settings = Environment.Configuration.Settings;
      //tmp.Configuration.Components = Environment.Configuration.Components;
      //tmp.Settings = Environment.Settings;
      //tmp.Components = Environment.Components;

      //tmp.Libraries = Environment.Libraries;

      MemoryStream m = new MemoryStream();
      DataContractJsonSerializer j3 = new DataContractJsonSerializer(typeof(SystemEnvironmentPersistables));
      j3.WriteObject(m, (SystemEnvironmentPersistables)tmp);

      FileStream fsj = new FileStream(pathJson, FileMode.Create, FileAccess.Write);
      fsj.Write(m.ToArray(), 0, (int)m.Length);

      return true;
    }






    public static string GetSystemPath()
    {
      //load some object from this assembly
      //to get path to it
      SystemEnvironmentPersistables t = new SystemEnvironmentPersistables();
      Assembly asm = Assembly.GetAssembly(t.GetType());
      FileInfo f = new FileInfo(asm.Location);

      string pathJson = f.Directory + "\\Petra.Gis.Environment.json";
      if (!File.Exists(pathJson))
        return pathJson;
      else
        return null;
    }


  }

}
